import { Component, OnInit, ViewChild } from '@angular/core'
import { ActivatedRoute } from '@angular/router'
import { AcquirerNewBaseClass } from '../baseClass'
import { FormBuilder } from '@angular/forms'
import { AcquirerStoreService } from '../acquirer-store.service'
import { ChannelAddMinusService } from '@shared/services/channelAddMinus.service'
import {
  IFormItem,
  FormItemType,
  EcPaymentBrandLabel,
  EcPaymentBrandValue,
  channelCode,
  ChanCodeValue,
} from '@shared/interfaces/common'
import { NzModalService, NzMessageService } from 'ng-zorro-antd'
import { CurrencyService } from '@shared/services/currency.service'
import { PageService } from '@shared/services/page.service'
import { AcquirerService } from '../../acquirer.service'
import { I18NService } from '@core'
import { BehaviorSubject, zip, Subject, Observable, combineLatest } from 'rxjs'
import { numScale } from 'app/utils/helpers'
import { deepCopy } from '@delon/util'
import { Acquirer, ECUPIChannel, ECVISChannel, ECMCCChannel, ECJCBChannel } from '@shared/interfaces/acquirer'
import { take, tap, combineAll } from 'rxjs/operators'
import { ECategoryUrl } from '@shared/interfaces/trade'
import { EcChannelService } from './ec-channel.service'

const isChanCodeSpan$ = new BehaviorSubject<string>('24')

@Component({
  selector: 'app-acquirer-new-ec-channel',
  templateUrl: './ec-channel.component.html',
  providers: [ChannelAddMinusService],
})
export class AcquirerNewEcChannelComponent extends AcquirerNewBaseClass implements OnInit {
  loading = true
  chanCodeOptions = []
  UPIChannelOptions = []
  VISChannelOptions = []
  // 添加卡渠道时的insCode和Acquirer
  insCode: any
  currentAcquirer: Acquirer

  chanCodeFormItem: IFormItem = {
    label: this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.PAYMENT_CHANNEL'),
    errTips: {
      required: this.trans('VALIDATION.REQUIRED_SELECT', {
        name: this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.PAYMENT_CHANNEL'),
      }),
    },
    errTip: this.trans('VALIDATION.REQUIRED_SELECT', {
      name: this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.PAYMENT_CHANNEL'),
    }),
    formControlName: 'chanCode',
    type: FormItemType.SELECT,
    compareFn: (o1, o2) => o1 === o2,
    multiple: 'default',
    allowClear: true,
    options: this.chanCodeOptions,
    change: this.handleChanCodeChange.bind(this),
  }
  formItemType = FormItemType
  currencyOptions = []
  formItems: IFormItem[] = [this.chanCodeFormItem]
  constructor(
    public fb: FormBuilder,
    public acquirerStore: AcquirerStoreService,
    private modal: NzModalService,
    public addMinusService: ChannelAddMinusService,
    public currencyService: CurrencyService,
    public pageService: PageService,
    public acquirerService: AcquirerService,
    private i18n: I18NService,
    public route: ActivatedRoute,
    private ecChannelService: EcChannelService,
    public msg: NzMessageService,
  ) {
    super(fb, acquirerStore)
  }

  ngOnInit() {
    this.insCode = this.route.snapshot.params['id']
    this.initAcquirer(this.insCode)
    this.initChanCodeOptions()
    this.initChannelOptions()
    this.initFormItems()
    this.initCurrencyOptions()
  }

  // 加载机构信息
  initAcquirer(insCode: any): void {
    if (insCode != null) {
      this.acquirerService
        .getOne(insCode)
        .pipe(take(1))
        .subscribe(acquirer => {
          this.currentAcquirer = acquirer
        })
    }
  }

  initChanCodeOptions(): void {
    for (const name in EcPaymentBrandLabel) {
      const option = {
        label: EcPaymentBrandLabel[name],
        value: EcPaymentBrandValue[name],
      }
      this.chanCodeOptions.push(option)
    }
  }

  initChannelOptions(): void {
    for (const name in channelCode) {
      const option = {
        label: channelCode[name],
        value: channelCode[name],
      }
      this.VISChannelOptions.push(option)
    }
    this.UPIChannelOptions = [
      {
        label: 'UPI',
        value: 'UPI',
      },
    ]
  }

  initCurrencyOptions(): void {
    zip(this.currencyService.getCurrencyOptions(), this.currencyService.getCurrencySearchOptions()).subscribe(value => {
      const [currencies, currencyCodes] = value
      if (currencies.length === 0 || currencyCodes.length === 0) {
        return
      }
      this.currencyOptions = currencies
      const { ecPayChannels } = this.acquirer
      this.initAddMinus(ecPayChannels)
      this.loading = false
    })
  }

  initFormItems(): void {
    this.formItems = [this.chanCodeFormItem]
  }

  initAddMinus(ecPayChannels): void {
    const generateFunc = (echannel: ECUPIChannel | ECMCCChannel | ECJCBChannel) => {
      const { chanCode } = echannel
      const rule = this.getGeneratedRule(chanCode, echannel)
      const formItems = this.getGeneratedFormItems(chanCode)
      return {
        rule,
        formItems,
      }
    }
    this.addMinusService.init(generateFunc, new ECUPIChannel(), ecPayChannels)
  }

  getGeneratedRule(paymentBrand: string, channel): any[] {
    return [this.generateValidateRules.call(this, paymentBrand || EcPaymentBrandValue.UPI, channel), {}]
  }

  getGeneratedFormItems(paymentBrand): any[] {
    switch (paymentBrand) {
      case 'UPI':
        return this.generateFormItems(paymentBrand)
      // case 'VIS':
      // case 'MCC':
      // case 'JCB':
      //   return this.generateFormItems(paymentBrand) && this.generateEcFormItems(paymentBrand)
      case 'KBank':
        return this.generateFormItems(paymentBrand)
      default:
        return this.generateFormItems(paymentBrand)
    }
  }

  generateValidateRules(
    paymentBrand: string,
    channel?: ECUPIChannel | ECVISChannel | ECMCCChannel | ECJCBChannel,
  ): { [key: string]: any } {
    switch (paymentBrand) {
      case EcPaymentBrandValue.UPI:
        return this.ecChannelService.genUPIValidateRules(channel as ECUPIChannel)
      // case EcPaymentBrandValue.VIS:
      //   return this.ecChannelService.genVISValidateRules(channel as ECVISChannel)
      // case EcPaymentBrandValue.MCC:
      //   return this.ecChannelService.genMCCValidateRules(channel as ECMCCChannel)
      // case EcPaymentBrandValue.JCB:
      //   return this.ecChannelService.genJCBValidateRules(channel as ECJCBChannel)
      case EcPaymentBrandValue.KBANK:
        return this.ecChannelService.genKBANKalidateRules(channel as ECVISChannel)
    }
  }

  generateFormItems(paymentBrand: string): IFormItem[] {
    switch (paymentBrand) {
      case EcPaymentBrandValue.UPI:
        return [
          this.chanCodeFormItem,
          ...deepCopy(
            this.ecChannelService.genUPIFormItems(
              this.currencyOptions,
              this.UPIChannelOptions,
              () => {},
              this.handleChanMerIdChange.bind(this),
            ),
          ),
        ]
      case EcPaymentBrandValue.KBANK:
        //   return [
        //     this.chanCodeFormItem]
        // // case EcPaymentBrandValue.VIS:
        // // case EcPaymentBrandValue.MCC:
        // // case EcPaymentBrandValue.JCB:
        return [
          this.chanCodeFormItem,
          ...deepCopy(
            this.ecChannelService.genKBankFormItems(
              this.currencyOptions,
              this.VISChannelOptions,
              () => {},
              this.handleChanMerIdChange.bind(this),
            ),
          ),
        ]
      default:
        return [this.chanCodeFormItem]
    }
  }

  // generateEcValidateRules(
  //   paymentBrand: string,
  //   channel?: ECVISChannel | ECMCCChannel | ECJCBChannel,
  // ): { [key: string]: any } {
  //   switch (paymentBrand) {
  //     case EcPaymentBrandValue.VIS:
  //       return this.ecChannelService.genVISValidateRules(channel as ECVISChannel)
  //     case EcPaymentBrandValue.MCC:
  //       return this.ecChannelService.genMCCValidateRules(channel as ECMCCChannel)
  //     case EcPaymentBrandValue.JCB:
  //       return this.ecChannelService.genJCBValidateRules(channel as ECJCBChannel)
  //   }
  // }

  // generateEcFormItems(paymentBrand: string): IFormItem[] {
  //   switch (paymentBrand) {
  //     case EcPaymentBrandValue.VIS:
  //     case EcPaymentBrandValue.MCC:
  //     case EcPaymentBrandValue.JCB:
  //       return [
  //         this.chanCodeFormItem,
  //         ...deepCopy(
  //           this.ecChannelService.genVISFormItems(
  //             this.currencyOptions,
  //             this.VISChannelOptions,
  //             this.handleEcChannelChange.bind(this),
  //             this.handleChanMerIdChange.bind(this),
  //           ),
  //         ),
  //       ]
  //     default:
  //       return [this.chanCodeFormItem]
  //   }
  // }

  checkValid(): boolean {
    const valid = this.addMinusService.valid
    if (valid) {
      this.pushDataToStore()
      this.msg.success(this.trans('GENERAL.NOTIFICATION.VALIDATION_SUCCESS'))
      return valid
    }
    this.addMinusService.makeDirty()
    this.msg.error(this.trans('GENERAL.NOTIFICATION.VALIDATION_FAIL'))
    return valid
  }

  pushDataToStore(): void {
    const ecPayChannels = this.addMinusService.values
    ecPayChannels.forEach(channel => {
      channel.fee = numScale(channel.fee, -2)
      if (channel.chanCode === ChanCodeValue.UPI) {
        channel.chanMerId = channel.acquiringIIN
      }
    })
    this.acquirer.ecPayChannels = ecPayChannels
  }

  handleChanCodeChange(paymentBrand: string, index: string | number): void {
    this.addMinusService.formItemsArr[index] = this.generateFormItems(paymentBrand)
    const formGroup = this.addMinusService.generateValidateForm([this.generateValidateRules(paymentBrand), {}])
    formGroup.get('chanCode').setValue(paymentBrand)
    this.addMinusService.validateForms[index] = formGroup
    this.addMinusService.isNeedValidateArr[index] = true
  }

  // handleEcChannelChange(chanCode: string, index: string | number): void {
  //   const paymentBrand = this.addMinusService.values[index].paymentBrand
  //   // this.addMinusService.formItemsArr[index] = this.generateEcFormItems(paymentBrand)
  //   const formGroup = this.addMinusService.generateValidateForm([this.generateEcValidateRules(paymentBrand), {}])
  //   formGroup.get('paymentBrand').setValue(paymentBrand)
  //   formGroup.get('chanCode').setValue(chanCode)
  //   this.addMinusService.validateForms[index] = formGroup
  //   this.addMinusService.isNeedValidateArr[index] = true
  // }

  handleChanMerIdChange(event, index: number): void {
    const paymentBrand = this.addMinusService.validateForms[index].get('chanCode').value
    const chanMerId = event.target.value
    const uniqueKey = this.getUniqueKey(paymentBrand)
    const valid = this.addMinusService.validateForms[index].get(uniqueKey).valid
    if (!valid) return
    if (!this.getChanMerIDValid(index, chanMerId, uniqueKey)) return
    if (this.insCode) {
      if (!this.getLocalMerIDValid(index, chanMerId, paymentBrand, uniqueKey)) return
    }
    this.acquirerService.getExistedChannel(paymentBrand, chanMerId, ECategoryUrl.ec).subscribe(channel => {
      this.modal.confirm({
        nzTitle: `<i>${this.trans('BIZ.ACQUIRER.CHANNEL.FOUND_MATCH_CHANNEL')}</i>`,
        nzContent: `<b>${this.trans('BIZ.ACQUIRER.CHANNEL.CONFIRM_TO_LOAD_CHANNEL_FOLLOW')} ${chanMerId}</b>`,
        nzOnOk: () => this.addMinusService.loadChannel(channel, index),
        nzOnCancel: () => this.clearChanCode(index, uniqueKey),
      })
    })
  }
  // 校验机构已存在的卡渠道
  getLocalMerIDValid(index, chanMerId, paymentBrand, uniqueKey): boolean {
    const { ecPayChannels = [] } = this.currentAcquirer
    let localUnique = true
    ecPayChannels.forEach(item => {
      if (item.paymentBrand === paymentBrand && item[uniqueKey] === chanMerId) {
        localUnique = false
      }
    })
    if (!localUnique) {
      this.addMinusService.validateForms[index].get(uniqueKey).setErrors({ existed: true })
    } else {
      this.addMinusService.validateForms[index].get(uniqueKey).setErrors(null)
    }
    return localUnique
  }

  getChanMerIDValid(index: number, chanMerId: string, uniqueKey: string): boolean {
    return this.addMinusService.checkChanMerIDUnique(index, chanMerId, uniqueKey, 'chanCode')
  }

  getUniqueKey(paymentBrand: EcPaymentBrandValue): string {
    switch (paymentBrand) {
      case EcPaymentBrandValue.UPI:
        return 'acquiringIIN'
        // case EcPaymentBrandValue.VIS:
        // case EcPaymentBrandValue.MCC:
        // case EcPaymentBrandValue.JCB:
        return 'chanMerId'
      case EcPaymentBrandValue.KBANK:
        return 'chanMerId'
    }
  }

  clearChanCode(index: number, uniqueKey: string): void {
    this.addMinusService.validateForms[index].get(uniqueKey).setValue(null)
  }

  computeChannelSectionHeader(idx: number): string {
    return `${this.trans('BIZ.ACQUIRER.OTHER.CHANNEL.CHANNEL_CONFIG')} ${idx + 1}`
  }

  private trans(str: string, params?: Object): string {
    return this.i18n.fanyi(str, params)
  }
}
